﻿using CqCore.Commands;
using CqCore.Logging;
using CqCore.Redis;
using Microsoft.Extensions.Options;
using Newtonsoft.Json.Linq;
using SuperShopInfrastructure.Extensions;
using SuperShopInfrastructure.FileUploader;
using SuperShopInfrastructure.Models.Order;
using SuperShopInfrastructure.Models.Product;
using SuperShopInfrastructure.Services;
using SuperShopInfrastructure.Static;
using SuperShopInfrastructure.Weixin.Services;
using SuperShopRepository;
using SuperShopService.IServices;
using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UploadService.Option;

namespace SuperShopService.Services
{
    public class ProductService : IProductService
    {
        private readonly IRedisService redisService;
        private readonly ProductRepository productRepository;
        private readonly ILogRecorder<ProductService> logRecorder;
        private readonly ImageServiceOption imageServiceOption;
        private readonly IShopAppService shopAppService;
        private readonly WeiXinHelper weiXinHelper;
        private readonly CqProductUploader cqProductUploader;
        private readonly DrawQRImageService drawQRImageService;

        public ProductService(
            IRedisService redisService,
            ProductRepository productRepository,
            ILogRecorder<ProductService> logRecorder,
            IOptions<ImageServiceOption> options,
            IShopAppService shopAppService,
            WeiXinHelper weiXinHelper,
            DrawQRImageService drawQRImageService)
        {
            this.redisService = redisService;
            this.productRepository = productRepository;
            this.logRecorder = logRecorder;
            this.imageServiceOption = options.Value;
            this.shopAppService = shopAppService;
            this.weiXinHelper = weiXinHelper;
            this.drawQRImageService = drawQRImageService;
            this.cqProductUploader = new CqProductUploader(this.imageServiceOption);
        }

        public async Task<HomeProductDataViewModel> GetHomeData(int shopAppId,int said)
        {
            var result = await redisService.GetOrSet<HomeProductDataViewModel>("GetHomeData_" + said, async () =>
            {
                var res = new HomeProductDataViewModel();
                var ds = await productRepository.GetHomeData(shopAppId);
                if (DataManager.CheckDs(ds, 3))
                {
                    if (DataManager.CheckHasRow(ds.Tables[0]))
                    {
                        foreach (DataRow dr in ds.Tables[0].Rows)
                        {
                            res.Banners.Add(new ProductItem()
                            {
                                Id = SecretClass.EncryptQueryString(dr["ProductId"].ToString()),
                                ShopAdminId = SecretClass.EncryptQueryString(dr["ShopAdminId"].ToString()),
                                ImgPath = imageServiceOption.ImgHost + dr["ImgPath"].ToString()
                            });
                        }
                    }
                    if (DataManager.CheckHasRow(ds.Tables[1]))
                    {
                        foreach (DataRow dr in ds.Tables[1].Rows)
                        {
                            res.NewRecommends.Add(new ProductItem()
                            {
                                Id = SecretClass.EncryptQueryString(dr["Id"].ToString()),
                                ImgPath = imageServiceOption.ImgHost + dr["ImgPath"].ToString(),
                                ProductName = dr["ProductName"].ToString(),
                                Brand = dr["Brand"].ToString(),
                                Title = dr["Title"].ToString(),
                                ShopAdminId = SecretClass.EncryptQueryString(dr["ShopAdminId"].ToString()),
                                SallPrice = DataManager.GetRowValue_Decimal(dr["SallPrice"])
                            });
                        }
                    }
                    if (DataManager.CheckHasRow(ds.Tables[2]))
                    {
                        foreach (DataRow dr in ds.Tables[2].Rows)
                        {
                            res.Hots.Add(new ProductItem()
                            {
                                Id = SecretClass.EncryptQueryString(dr["Id"].ToString()),
                                ImgPath = imageServiceOption.ImgHost + dr["ImgPath"].ToString(),
                                ProductName = dr["ProductName"].ToString(),
                                Brand = dr["Brand"].ToString(),
                                Title = dr["Title"].ToString(),
                                SallNum = DataManager.GetRowValue_Int(dr["SallNum"]),
                                ShopAdminId = SecretClass.EncryptQueryString(dr["ShopAdminId"].ToString()),
                                SallPrice = DataManager.GetRowValue_Decimal(dr["SallPrice"])
                            });
                        }
                    }
                }
                return res;

            });
            return result;
        }

        public async Task<CommandResult<string>> MakeOroductQrImage(MakeProductQrImageCommand command)
        {
            var cacheKey = "QrCode_Product_" + command.ProductId;
            var base64img = await redisService.Get<string>(cacheKey);
            if (base64img == null)
            {
                var shopAppModel = await shopAppService.GetShopAppModel(command.ShopID.ToInt());
                if (shopAppModel == null)
                    return CommandResult<string>.Failure("获取店铺模型出错");

                string tokenJson = weiXinHelper.GetAccessToken(shopAppModel.AppId, shopAppModel.AppSecret);
                JObject jo = JObject.Parse(tokenJson);
                string access_token = jo["access_token"].ToString();
                //直接请求二维码信息
                string path = "pages/product/detail?id=" + command.ProductId + "&said=" + shopAppModel.ShopAdminId;
                var ret = weiXinHelper.GetQrCode(access_token, path, 90);
                //存入redis
                await redisService.Set<string>(cacheKey, Convert.ToBase64String(ret), DateTime.Now.AddMonths(15));
                base64img = Convert.ToBase64String(ret);
            }

            //拼图
            //------
            var _fold = "qrproduct";
            var card_saveName = "qrp" + command.ProductId + ".jpg";
            var card_savePath = Path.Combine(cqProductUploader.TempPhysicalPath.Replace("Temp", _fold), card_saveName);

            string productname = "";
            string price = "";
            string productimgpath = "";
            string qrimgbase64 = "";

            productname = command.PECName;
            price = "￥" + command.PriceRanage;
            qrimgbase64 = base64img;
            productimgpath = command.ProductImage;
            var logValue = new
            {
                productid = command.ProductId,
                productname = productname,
                price = command.PriceRanage,
                productimgpath = productimgpath
            };
            logRecorder.Info(new EventData()
            {
                Type = "QRProductImage",
                Message = "QRProductImage.logValue",
                Labels = {
                            ["QRProductImage"] = logValue.ToJson()
                        }
            });

            // 生成二维码图片
            Bitmap result_map = drawQRImageService.QrProductImage(productname, price, productimgpath, qrimgbase64);
            // 名片存储地址
            result_map.Save(card_savePath, System.Drawing.Imaging.ImageFormat.Jpeg);
            var returnImgPath = imageServiceOption.ImgHost + "/" + _fold + "/" + card_saveName + "?r=" + new Random().Next(1, 10000);
            return CommandResult<string>.Success(returnImgPath);
        }

        public async Task<ProductSkuManagerModel> GetProductSkuManagerModel(int shopAdminId, string productId)
        {
            var res = new ProductSkuManagerModel();
            res.ProductId = SecretClass.EncryptQueryString(productId);
            var ds = await productRepository.GetProductSkuDs(shopAdminId, productId);
            if (DataManager.CheckDs(ds, 2))
            {
                //表1：获取当前商品单规格SKU数据
                //表2：获取当前商品的规格类型

                res.SkuType = Convert.ToInt32(ds.Tables[1].Rows[0]["CurrentSkuType"]);
                if (DataManager.CheckHasRow(ds.Tables[0]))
                {
                    DataRow dr = ds.Tables[0].Rows[0];
                    res.SingleSkuModel.Id = Convert.ToInt32(dr["Id"]);
                    res.SingleSkuModel.ProductId = res.ProductId;
                    res.SingleSkuModel.SallPrice = Convert.ToDecimal(dr["SallPrice"]);
                    res.SingleSkuModel.SkuCode = dr["SkuCode"].ToString();
                    res.SingleSkuModel.SkuType = 1;
                    res.SingleSkuModel.Weight = DataManager.GetRowValue_Float(dr["Weight"]);
                    res.SingleSkuModel.StockNum = Convert.ToInt32(dr["StockNum"]);
                }

            }
            return res;
        }
        public async Task<ProductSkuManagerModel> GetProductSkuManagerModel_AJAX(int shopAdminId, string productId)
        {
            var res = new ProductSkuManagerModel();
            res.ProductId = SecretClass.EncryptQueryString(productId);
            var ds = await productRepository.GetProductMoreSkuDs(shopAdminId, productId);
            if (DataManager.CheckDs(ds, 3))
            {
                //表1：获取当前商品多规格SKU数据
                //表2：获取当前商品多规格SKU属性数据
                //表3：获取当前商品多规格SKU属性值数据
                if (DataManager.CheckHasRow(ds.Tables[0]))
                {
                    foreach (DataRow dr in ds.Tables[0].Rows)
                    {
                        res.MoreSkuModelList.Add(new MoreSkuModel()
                        {
                            Id = Convert.ToInt32(dr["Id"]),
                            ProductId = res.ProductId,
                            PropetyCombineId = dr["PropetyCombineId"].ToString(),
                            ProppetyCombineName = dr["ProppetyCombineName"].ToString(),
                            StockNum = Convert.ToInt32(dr["StockNum"]),
                            SallPrice = Convert.ToDecimal(dr["SallPrice"]),
                            Weight = DataManager.GetRowValue_Float(dr["Weight"]),
                            SkuType = 2,
                            SkuCode = dr["SkuCode"].ToString()
                        });
                    }
                }
                if (DataManager.CheckHasRow(ds.Tables[1]))
                {
                    foreach (DataRow dr in ds.Tables[1].Rows)
                    {
                        res.Product_Sall_PropetyModelList.Add(new Product_Sall_PropetyModel()
                        {
                            Id = Convert.ToInt32(dr["Id"]),
                            PropetyName = dr["PropetyName"].ToString(),
                            ProductId = res.ProductId
                        });
                    }

                }

                if (DataManager.CheckHasRow(ds.Tables[2]))
                {
                    foreach (DataRow dr in ds.Tables[2].Rows)
                    {
                        res.Product_Sall_Propety_ValueModelList.Add(new Product_Sall_Propety_ValueModel()
                        {
                            Id = Convert.ToInt32(dr["Id"]),
                            SallPropetyId = Convert.ToInt32(dr["SallPropetyId"]),
                            PropetyValue = dr["PropetyValue"].ToString(),
                            ProductId = res.ProductId
                        });
                    }

                }
                //将属性值模型，分别装入属性名称属性中
                if (res.Product_Sall_PropetyModelList.Count > 0)
                {
                    foreach (var propety in res.Product_Sall_PropetyModelList)
                    {
                        var _propetyValueList = res.Product_Sall_Propety_ValueModelList.Where(p => p.SallPropetyId == propety.Id).ToList();
                        propety.Product_Sall_Propety_ValueList.AddRange(_propetyValueList);
                    }
                }
            }
            return res;
        }

        public async Task<List<CreaterOrder_CheckItem>> GetCreateOrder_CheckItemList(string skuids)
        {
            //验证
            if (ToolManager.IsSqlin(skuids))
            {
                logRecorder.Error(new EventData()
                {
                    Type = "ProductService.GetCreateOrder_CheckItemList",
                    Message = "发生sql注入",
                    Labels = {
                            ["parms"] = skuids
                        }
                });
                return null;
            }
            var queryList = new List<CreaterOrder_CheckItem>();
            var ds = await productRepository.GetCreateOrder_CheckItemDs(skuids);
            if (DataManager.CheckDs(ds, 1) && DataManager.CheckHasRow(ds.Tables[0]))
            {
                foreach (DataRow dr in ds.Tables[0].Rows)
                {
                    queryList.Add(new CreaterOrder_CheckItem()
                    {
                        ProductSkuId = Convert.ToInt32(dr["ProductSkuId"]),
                        StockNum = Convert.ToInt32(dr["StockNum"]),
                        IsDel = Convert.ToInt32(dr["IsDel"]),
                        Product_OptionStatus = Convert.ToInt32(dr["Product_OptionStatus"]),
                        Product_IsDel = Convert.ToInt32(dr["Product_IsDel"]),
                        ProductName = dr["ProductName"].ToString(),
                        ProppetyCombineName = dr["ProppetyCombineName"].ToString(),
                        SallPrice = DataManager.GetRowValue_Decimal(dr["SallPrice"]),
                        SkuCode = dr["SkuCode"].ToString(),
                        PropetyCombineId = dr["PropetyCombineId"].ToString(),
                        Weight = DataManager.GetRowValue_Float(dr["Weight"])
                    });
                }
            }
            return queryList;
        }

        public async Task<List<MenuItemViewModel>> GetMenuList(int shopAdminId)
        {
            var result = await redisService.GetOrSet<List<MenuItemViewModel>>("GetMenuList_" + shopAdminId, async () =>
            {
                var res = new List<MenuItemViewModel>();
                var ds = await productRepository.GetMenuList(shopAdminId);
                if (DataManager.CheckDs(ds, 1))
                {
                    foreach (DataRow dr in ds.Tables[0].Rows)
                    {
                        res.Add(new MenuItemViewModel()
                        {
                            Id = Convert.ToInt32(dr["Id"].ToString()),
                            MenuName = dr["MenuName"].ToString(),
                            IsAll = DataManager.GetRowValue_Int(dr["IsAll"]),
                            ImgPath = imageServiceOption.ImgHost + dr["ImgPath"].ToString()
                        });
                    }
                }
                return res;
            });
            return result;
        }

        public async Task<ProductDetailViewModel> GetProduct(int id)
        {
            var result = await redisService.GetOrSet<ProductDetailViewModel>("GetProductDetail_" + id, async () =>
            {
                
                var ds = await productRepository.GetProduct(id);
                if (DataManager.CheckDs(ds, 2) && DataManager.CheckHasRow(ds.Tables[0]) && DataManager.CheckHasRow(ds.Tables[1]))
                {
                    var res = new ProductDetailViewModel();
                    var dr = ds.Tables[0].Rows[0];
                    res.Id = SecretClass.EncryptQueryString(dr["Id"].ToString());
                    res.ProductName = dr["ProductName"].ToString();
                    res.Brand = dr["Brand"].ToString();
                    res.Title = dr["Title"].ToString();
                    res.MenuId = Convert.ToInt32(dr["MenuId"]);
                    res.ShipTemplateId = DataManager.GetRowValue_Int(dr["ShippingTemplateId"]);
                    res.Unit = dr["Unit"].ToString();
                    res.CurrentSkuType = Convert.ToInt32(dr["CurrentSkuType"]);
                    res.Detail = dr["ProductDetail"].ToString();
                    res.MinAmount = DataManager.GetRowValue_Decimal(dr["MinAmount"]);
                    res.MaxAmount = DataManager.GetRowValue_Decimal(dr["MaxAmount"]);
                    res.BannerImgs = new List<string>();
                    foreach (DataRow dr_img in ds.Tables[1].Rows)
                    {
                        res.BannerImgs.Add(imageServiceOption.ImgHost + dr_img["ImagePath"].ToString());
                    }
                    return res;
                }
                return null;
            });
            return result;
        }

        public async Task<List<ProductListViewModel>> QueryProductList(QueryProductListCriteria criteria)
        {
            List<ProductListViewModel> res = null;
            if (string.IsNullOrEmpty(criteria.keyWord) && criteria.MenuId == 0)
            {
                res = await redisService.GetOrSet<List<ProductListViewModel>>("GetProductList_" + criteria.Spid + "_Offset_" + criteria.OffSet, async () =>
                {
                    return await BaseQueryProductList(criteria);
                });
            }
            else
            {
                res = await BaseQueryProductList(criteria);
            }
            return res;
        }

        private async Task<List<ProductListViewModel>> BaseQueryProductList(QueryProductListCriteria criteria)
        {
            var queries = new List<ProductListViewModel>();
            var ds = await productRepository.GetProductList(criteria);
            if (DataManager.CheckDs(ds, 1))
            {
                foreach (DataRow dr in ds.Tables[0].Rows)
                {
                    queries.Add(new ProductListViewModel()
                    {
                        Id = SecretClass.EncryptQueryString(dr["Id"].ToString()),
                        ImgPath = imageServiceOption.ImgHost + dr["ImgPath"].ToString(),
                        ProductName = dr["ProductName"].ToString(),
                        Brand = dr["Brand"].ToString(),
                        Title = dr["Title"].ToString(),
                        ShopAdminId = SecretClass.EncryptQueryString(dr["ShopAdminId"].ToString()),
                        SallPrice = DataManager.GetRowValue_Decimal(dr["SallPrice"])
                    });
                }
            }
            return queries;
        }

        public async Task<List<SpecialPlaceViewModel>> SpecialPlaceList(int shopAdminId,int type)
        {
            var result = await redisService.GetOrSet<List<SpecialPlaceViewModel>>("SpecialPlaceList" + shopAdminId+"_"+type, async () =>
            {
                var res = new List<SpecialPlaceViewModel>();
                var ds = await productRepository.SpecialPlaceList(shopAdminId,type);
                if (DataManager.CheckDs(ds, 1))
                {
                    foreach (DataRow dr in ds.Tables[0].Rows)
                    {
                        res.Add(new SpecialPlaceViewModel()
                        {
                            Id = Convert.ToInt32(dr["Id"].ToString()),
                            PlaceName = dr["PlaceName"].ToString(),
                            Sorft = Convert.ToInt32(dr["Sorft"]),
                            OptionStatus = Convert.ToInt32(dr["OptionStatus"]),
                            ImgPath = dr["ImgPath"] == DBNull.Value ? "" : imageServiceOption.ImgHost + dr["ImgPath"].ToString(),
                            MenuName = dr["MenuName"].ToString(),
                            MenuId = Convert.ToInt32(dr["MenuId"])

                        });
                    }
                }
                return res;
            });
            return result;
        }
    }
}
